import IsPC from "@/methods/IsPc";
import { Color, SpotI } from '@/utils/CanvasUtils/CanvasType';
import Paint from "@/paint/Paint";
import { GameLevel, LevelMessage, padding, style } from "@/paint/Setting";
import Angle from '@/paint/utils/Angle';
import Vector from '@/paint/utils/Vector';
import Point from '@/paint/utils/Point';
import BaseView from '@/paint/view/BaseView';
import VectorLineElement from "@/paint/elements/VectorLineElement";

export default class GameMakeView extends BaseView {

	/** 地图信息 */
	private levelMessage!: LevelMessage;

	/** 鼠标悬停的线条 */
	private MouseHoverLine?: VectorLineElement;

	/** 为PC端 */
	private IsPc: boolean = IsPC();

	/** 鼠标样式 */
	public get MousePointer(): boolean {
		return this.Paint.Canvas.Element.style.cursor === "pointer";
	}

	public set MousePointer(isPointer: boolean) {
		this.Paint.Canvas.Element.style.cursor = isPointer ? "pointer" : "";
	}

	/** 内边距 */
	public get Padding(): number {
		return this.levelMessage.padding;
	}

	public set Padding(val: number) {
		this.levelMessage.padding = val;
		this.MakeUI();
	}

	/** 蜂巢维度 */
	public get Dimensional(): number {
		return this.levelMessage.dimensional;
	}

	public set Dimensional(val: number) {
		this.levelMessage.dimensional = val;
		this.GetMapData();
	}

	/** 关卡名称 */
	public get Name(): string {
		return this.levelMessage.name;
	}

	public set Name(val: string) {
		this.levelMessage.name = val;
	}

	/** 根据三视图解图 */
	public get Order(): boolean {
		return this.levelMessage.order;
	}

	public set Order(val: boolean) {
		this.levelMessage.order = val;
	}

	/** 线条颜色 */
	public get Color(): Color {
		return this.levelMessage.style.Color;
	}

	public set Color(val: Color) {
		this.levelMessage.style.Color = val;
	}

	/** 悬停颜色 */
	public get HoverColor(): Color {
		return this.levelMessage.style.HoverColor;
	}

	public set HoverColor(val: Color) {
		this.levelMessage.style.HoverColor = val;
	}

	/** 激活颜色 */
	public get ActiveColor(): Color {
		return this.levelMessage.style.ActiveColor;
	}

	public set ActiveColor(val: Color) {
		this.levelMessage.style.ActiveColor = val;
	}

	/** 虚线颜色 */
	public get DottedColor(): Color {
		return this.levelMessage.style.DottedColor;
	}

	public set DottedColor(val: Color) {
		this.levelMessage.style.DottedColor = val;
	}

	/** 线条宽度 */
	public get LineWidth(): number {
		return this.levelMessage.style.LineWidth;
	}

	public set LineWidth(val: number) {
		this.levelMessage.style.LineWidth = val;
	}

	/** 悬停宽度 */
	public get HoverLineWidth(): number {
		return this.levelMessage.style.HoverLineWidth;
	}

	public set HoverLineWidth(val: number) {
		this.levelMessage.style.HoverLineWidth = val;
	}

	/** 激活宽度 */
	public get ActiveLineWidth(): number {
		return this.levelMessage.style.ActiveLineWidth;
	}

	public set ActiveLineWidth(val: number) {
		this.levelMessage.style.ActiveLineWidth = val;
	}

	/** 虚线宽度 */
	public get DottedLineWidth(): number {
		return this.levelMessage.style.DottedLineWidth;
	}

	public set DottedLineWidth(val: number) {
		this.levelMessage.style.DottedLineWidth = val;
	}

	/** 小地图内容 */
	public get MapString(): string {
		const {
			Name: name,
			Order,
			Padding: padding,
			Dimensional: dimensional,
			Color,
			LineWidth,
			HoverColor,
			HoverLineWidth,
			ActiveColor,
			ActiveLineWidth,
			DottedColor,
			DottedLineWidth
		} = this;
		const { viewMap, map } = this.levelMessage;
		return JSON.stringify({
			name,
			padding,
			dimensional,
			Order,
			viewMap,
			map,
			style: {
				Color,
				LineWidth,
				HoverColor,
				HoverLineWidth,
				ActiveColor,
				ActiveLineWidth,
				DottedColor,
				DottedLineWidth
			}
		}, null, "\t");
	}

	/** 地图数据 */
	public get MapData(): LevelMessage {
		return { ...this.levelMessage };
	}

	/** 地图内容 */
	public set MapString(val: string) {
		// 不允许修改
		this.levelMessage = { ...this.levelMessage };
	}

	/**
	 * 构造函数
	 * @param el 画板元素
	 */
	public constructor(el: HTMLCanvasElement) {
		super(el);
		this.InitMapData();
	}

	private InitMapData(): void {
		if (false) {
			this.levelMessage = GameLevel[38];
			this.MakeUI();
		} else {
			this.levelMessage = {
				name: "自定义关卡",
				padding,
				style,
				dimensional: 4,
				order: true,
				viewMap: [],
				map: []
			};
			this.GetMapData();
		}
	}

	/** 获取地图数据 */
	private GetMapData(): void {
		const val = this.Dimensional;
		const viewMap = new Array((2 * val * val + 2 * val) * 3).fill(0);
		const startMap = new Array((3 * val * val + val) * 3).fill(0);
		this.levelMessage.viewMap = viewMap;
		this.levelMessage.map = startMap;
		this.MakeUI();
	}

	/** 重新计算界面 */
	private MakeUI(): void {
		const { padding, dimensional } = this.levelMessage;
		const canvas = this.Paint.Canvas.Element;
		const X = padding;
		const Y = padding;
		const Width = canvas.width - padding * 2;
		const Height = canvas.height - padding * 2;
		const angleRatio = Math.cos(new Angle(30).Value);
		const Height2 =
			Width / angleRatio + (Width / (dimensional * 3 + 2)) * dimensional + 50;
		const minHeigt = Math.min(Height, Height2);
		const ViewLength =
			(minHeigt - 50) / ((dimensional * 3 + 2) / angleRatio + dimensional);
		const calcWidth = (Width - ViewLength * (dimensional * 3 + 2)) / 2;
		const length =
			(ViewLength * (dimensional * 3 + 2)) / angleRatio / (dimensional * 2);
		this.Clear();
		this.MakeView(ViewLength, { X: X + calcWidth, Y: Y + 24 });
		this.MakeBody(length, {
			X: X + calcWidth,
			Y: Y + ViewLength * dimensional + 50
		});
		this.Paint.AddEvent(this, "resize", () => {
			this.MakeUI();
		});
	}

	/** 添加小地图元素 */
	private MakeView(length: number, spot: SpotI): void {
		const paint: Paint = this.Paint;
		const { dimensional } = this.levelMessage;
		const sideLength = length * dimensional;
		const Radius = sideLength / 20;
		const viewList: Vector[] = [];
		const leftTop = new Vector(
			new Point(spot.X, spot.Y),
			new Angle(90),
			length
		);
		const viewOrigin = leftTop.RotateAngle(-90);
		const round = viewOrigin
			.RotateAngle(90)
			.ToLength(sideLength)
			.RotateAngle(-90)
			.ToLength(sideLength / 2)
			.RotateAngle(90)
			.ToLength(Radius * 2);
		paint.CreatElement("round", {
			Spot: round.Start,
			Radius,
			StartAngle: new Angle(0),
			EndAngle: new Angle(360),
			BorderColor: "#000",
			LineWidth: Radius / 3
		});
		const viewTypeList = ["正视图", "侧视图", "俯视图"];
		for (let i = 0; i < 3; i++) {
			const viewFirst = viewOrigin
				.SetLength(length * (dimensional + 1) * i)
				.To()
				.SetLength(length);
			const firstLine = viewFirst.RotateAngle(90);
			for (let m = 0; m < dimensional; m++) {
				const lineOrigin = firstLine
					.SetLength(length * m)
					.To()
					.SetLength(length);
				if (m === 0) {
					const font = lineOrigin
						.RotateAngle(-90)
						.ToLength(sideLength / 2)
						.RotateAngle(-90);
					const { X, Y } = font.Start;
					paint.CreatElement("text", {
						Spot: { X, Y: Y - 5 },
						Text: viewTypeList[i],
						Color: "#000",
						BaseLine: "bottom",
						Align: "center",
						FontSize: 18
					});
				}
				viewList.push(lineOrigin);
			}
			for (let i = 0; i < dimensional; i++) {
				const colOrigin = viewFirst
					.SetLength(length * i)
					.To()
					.SetLength(length);
				viewList.push(colOrigin);
				const colFirst = colOrigin.To().RotateAngle(90);
				for (let j = 0; j < dimensional; j++) {
					const rowOrigin = colFirst
						.SetLength(length * j)
						.To()
						.SetLength(length);
					viewList.push(rowOrigin);
					viewList.push(rowOrigin.To().RotateAngle(90));
				}
			}
		}
		this.AddViewEvent(viewList);
	}

	/** 添加小地图事件 */
	private AddViewEvent(viewList: Vector[]): void {
		const paint: Paint = this.Paint;
		const { viewMap, style } = this.levelMessage;
		viewList.forEach((view, i) => {
			const val = viewMap[i];
			const type = val === 2 ? "dotted" as const : val === 1 ? "active" as const : "none" as const;
			const vector = { type, Vector: view, style, Disabled: false, Range: 45 };
			const element = paint.CreatElement("vector", vector);
			element.AddEvent("hover", () => {
				this.VectorHover(element);
			});
			element.AddEvent("click", () => {
				this.VectorClick(element, false);
				const type = element.Type;
				this.SetViewMap(i, type === "active" ? 1 : type === "dotted" ? 2 : 0);
			});
		});
	}

	/** 添加蜂巢元素 */
	private MakeBody(length: number, spot: SpotI): void {
		const paint: Paint = this.Paint;
		const { dimensional } = this.levelMessage;
		const sideLength = length * dimensional;
		const Radius = sideLength / 30;
		const half = length * (dimensional / 2);
		const vectorList: Vector[] = [];
		const leftTop = new Vector(
			new Point(spot.X, spot.Y),
			new Angle(90),
			length
		);
		const origin = leftTop
			.ToLength(half)
			.RotateAngle(-60)
			.ToLength(length * dimensional)
			.RotateAngle(180);
		const round = origin
			.RotateAngle(-120)
			.ToLength(half)
			.RotateAngle(-60)
			.ToLength(half)
			.ToLength(Radius * 2);
		paint.CreatElement("round", {
			Spot: round.Start,
			Radius,
			StartAngle: new Angle(0),
			EndAngle: new Angle(360),
			BorderColor: "#000",
			LineWidth: Radius / 3
		});
		for (let i = 0; i < 3; i++) {
			const firstLine = origin.RotateAngle(i * 120);
			for (let m = 0; m < dimensional; m++) {
				vectorList.push(
					firstLine
						.SetLength(length * m)
						.To()
						.SetLength(length)
				);
			}
			const groupOrigin = firstLine
				.SetLength(length * dimensional)
				.To()
				.SetLength(length)
				.RotateAngle(120);
			for (let j = 1; j <= dimensional; j++) {
				const firstGroup = groupOrigin
					.SetLength(length * j)
					.To()
					.SetLength(length)
					.RotateAngle(60);
				for (let k = 0; k < dimensional; k++) {
					const firstRow = firstGroup
						.SetLength(length * k)
						.To()
						.SetLength(length);
					vectorList.push(firstRow);
					vectorList.push(firstRow.RotateAngle(60));
					vectorList.push(firstRow.RotateAngle(120));
				}
			}
		}
		this.AddBodyEvent(vectorList);
	}

	/** 添加蜂巢事件 */
	private AddBodyEvent(vectorList: Vector[]): void {
		const paint: Paint = this.Paint;
		const { map, style } = this.levelMessage;
		vectorList.forEach((vector, i) => {
			const type = map[i] === 1 ? "active" as const : "none" as const;
			const vectorI = { type, Vector: vector, style, Disabled: false, Range: 30 };
			const element = paint.CreatElement("vector", vectorI);
			element.AddEvent("hover", () => {
				this.VectorHover(element);
			});
			element.AddEvent("click", () => {
				this.VectorClick(element, true);
				this.SetMap(i, element.Type === "active" ? 1 : 0);
			});
		});
	}

	/** 悬停蜂巢线条 */
	private VectorHover(element: VectorLineElement): void {
		const type = element.Type;
		const isPc = this.IsPc;
		const onHover = element.OnHover;
		if (type !== "active" && type !== "dotted") {
			element.Type = isPc && onHover ? "hover" : "none";
		}
		if (this.IsPc) {
			this.VectorMouseCursor(element);
		}
	}

	/** 悬停蜂巢线条的鼠标样式 */
	private VectorMouseCursor(vectorElement: VectorLineElement): void {
		if (vectorElement.OnHover) {
			this.MousePointer = true;
			this.MouseHoverLine = vectorElement;
		} else if (this.MouseHoverLine === vectorElement) {
			this.MousePointer = false;
		}
	}

	/** 单击蜂巢线条 */
	private VectorClick(element: VectorLineElement, isVector: boolean): void {
		const type = element.Type;
		const isPc = this.IsPc;
		const onHover = element.OnHover;
		if (type === "none" || type === "hover") {
			element.Type = "active";
		} else if (type === "active") {
			element.Type = !isVector ? "dotted" : isPc && onHover ? "hover" : "none";
		} else if (!isVector && type === "dotted") {
			element.Type = isPc && onHover ? "hover" : "none";
		}
	}

	/** 设置小地图数据 */
	private SetViewMap(index: number, val: number): void {
		this.levelMessage.viewMap[index] = val;
		this.levelMessage.viewMap = [...this.levelMessage.viewMap];
	}

	/** 设置地图数据 */
	private SetMap(index: number, val: number): void {
		this.levelMessage.map[index] = val;
		this.levelMessage.map = [...this.levelMessage.map];
	}
}
